﻿Imports PTIC_GestionBDD
Imports PTIC_Util
Imports PTIC_Util.GestionCalculs
Imports Actuariat.Comptes
Imports Actuariat
Imports System.Data
Imports OMANE.Common.Model.Interfaces
Imports OMANE.Common.Model.Parametrage

Namespace moteurTauxGaranti1
    ''' <summary>
    ''' Moteur de calcul du taux garanti par la méthode de l'équilibre technique - VersionSAS
    ''' </summary>
    ''' <remarks></remarks>
    Public Class IntegMoteur_MethodeEqTarif_V2
        Inherits Traitement
        Implements IIntegMoteur_MethodeEqTarif

        Dim Optimise As Boolean = False
        Dim TempsChgtTable As Double = 0
        Dim TimeChgtTable1 As Double = 0
        Dim TimeChgtTable2 As Double = 0
        Dim TempsFonctCalculPrinc As Double = 0
        Dim TimeFonctCalculPrinc1 As Double = 0
        Dim TimeFonctCalculPrinc2 As Double = 0
        Dim TempsFonctCalculSecondaire As Double = 0
        Dim TimeFonctCalculSecondaire1 As Double = 0
        Dim TimeFonctCalculSecondaire2 As Double = 0

#Region "Variables de classe"
        'Collection de paramètres de l'étude en cours
        Protected _coll_param As ParametresList
        'Table contenant les segments et toutes leurs caractéristiques
        Protected _tble_travail As DataTable
        'Tables de mortalité H/F, maintien INCAP/INVAL hors franchise, coefficients de réduction à appliquer à cause de la franchise
        Protected m_tble_mortalite_H As ITableMortalite, m_tble_mortalite_F As ITableMortalite
        Private m_TbleINCINVTaux As ITableMaintienINCINV_Tx
        Private m_TbleINCINVFra As ITableMaintienINCINV_Fra
        'Résultats du calcul / Scénario central / Simulations
        Protected _resultatsCalcul As resultatsMoteur1
        Protected _scenarioCentral As scenarioCentralMoteur1
        Protected _simulations As simulationsMoteur1
#End Region

#Region "Création d'une instance"
        ''' <summary>
        ''' Constructeur
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub New(ByVal nom As String, _
                       ByVal coll_Param As ParametresList, _
                       ByVal TraitEntreeModeleEqTarif As Traitement, _
                       ByVal DataSetOMANE As DataSet, _
                       ByVal Referentiel As IReferentielOMANE)
            MyBase.New(nom, Nothing)
            m_Referentiel = Referentiel
            m_TraitementEntree = TraitEntreeModeleEqTarif
            AddHandler m_TraitementEntree.EtatCalculDataTableAChange, AddressOf onTraitEntree_EtatCalculDataTableChanged

            m_DataSet = DataSetOMANE
            'Collection de paramètres afférents à l'étude en cours
            _coll_param = coll_Param
            'Objet permettant de stocker les résultats du moteur et du scénario central
            _resultatsCalcul = New resultatsMoteur1()
            _scenarioCentral = New scenarioCentralMoteur1(Me)
            _simulations = New simulationsMoteur1(Me)
            _simulations.AjouteFonctionCalculIntermediaire(_scenarioCentral)
            addHandlers()
        End Sub
#End Region

#Region "Propriétés"
        Private m_Referentiel As IReferentielOMANE
        Public ReadOnly Property Referentiel As IReferentielOMANE Implements IIntegMoteur_MethodeEqTarif.Referentiel
            Get
                Return m_Referentiel
            End Get
        End Property

        Private m_DataSet As DataSet
        Public ReadOnly Property DataSetOMANE As DataSet Implements IIntegMoteur_MethodeEqTarif.DataSetOMANE
            Get
                Return m_DataSet
            End Get
        End Property

        Private m_TraitementEntree As Traitement
        Public ReadOnly Property TraitementEntree As Traitement Implements IIntegMoteur_MethodeEqTarif.TraitementEntree
            Get
                Return m_TraitementEntree
            End Get
        End Property

        ''' <summary>
        ''' Liste des paramètres utilisés dans les calculs
        ''' </summary>
        ''' <remarks></remarks>
        Public Property listeParametres() As ParametresList Implements IIntegMoteur_MethodeEqTarif.listeParametres
            Get
                Return _coll_param
            End Get
            Set(ByVal value As ParametresList)
                If Not value Is _coll_param Then
                    RemoveHandlersListeParametres()
                    _coll_param = value
                    addHandlersListeParametres()
                End If
            End Set
        End Property

        ''' <summary>
        ''' Etat de calcul du scénario central
        ''' </summary>
        ''' <remarks></remarks>
        Public ReadOnly Property etatCalculScenCentral() As ValueEtatCalcul Implements IIntegMoteur_MethodeEqTarif.etatCalculScenCentral
            Get
                Return _scenarioCentral.EtatCalcul
            End Get
        End Property

        ''' <summary>
        ''' Etat de calcul des simulations
        ''' </summary>
        ''' <remarks></remarks>
        Public ReadOnly Property etatCalculSimulations() As ValueEtatCalcul Implements IIntegMoteur_MethodeEqTarif.etatCalculSimulations
            Get
                Return simulations.EtatCalcul
            End Get
        End Property

        ''' <summary>
        ''' Table en entrée utilisée dans la procédure de calcul et issue des encours retraités
        ''' </summary>
        ''' <remarks></remarks>
        Public ReadOnly Property tableTravail() As DataTable Implements IIntegMoteur_MethodeEqTarif.tableTravail
            Get
                Return _tble_travail
            End Get
        End Property

        ''' <summary>
        ''' Scénario central du moteur de calcul 1
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public ReadOnly Property ScenarioCentral As scenarioCentralMoteur1 Implements IIntegMoteur_MethodeEqTarif.ScenarioCentral
            Get
                Return _scenarioCentral
            End Get
        End Property

        ''' <summary>
        ''' Prime pure résultant du dernier calcul du moteur
        ''' </summary>
        ''' <remarks></remarks>
        Public ReadOnly Property PPurePf() As Double Implements IIntegMoteur_MethodeEqTarif.PPurePf
            Get
                Return _resultatsCalcul.PPurePf
            End Get
        End Property

        ''' <summary>
        ''' Prime technique résultant du dernier calcul du moteur
        ''' </summary>
        ''' <remarks></remarks>
        Public ReadOnly Property PTechPf() As Double Implements IIntegMoteur_MethodeEqTarif.PTechPf
            Get
                Return _resultatsCalcul.PTechPf
            End Get
        End Property

        ''' <summary>
        ''' Somme des capitaux résultant du dernier calcul du moteur
        ''' </summary>
        ''' <remarks></remarks>
        Public ReadOnly Property sommeCSR() As Double Implements IIntegMoteur_MethodeEqTarif.sommeCSR
            Get
                Return _resultatsCalcul.sommeCSR
            End Get
        End Property

        ''' <summary>
        ''' Somme des capitaux sous rique du scénario central
        ''' </summary>
        ''' <remarks></remarks>
        Public ReadOnly Property sommeCSR_ScenCentral() Implements IIntegMoteur_MethodeEqTarif.sommeCSR_ScenCentral
            Get
                Return _scenarioCentral.resultats.sommeCSR
            End Get
        End Property

        ''' <summary>
        ''' Simulations attachées au moteur de calcul
        ''' </summary>
        ''' <remarks></remarks>
        Public ReadOnly Property simulations() As IsimulationsMoteur1 Implements IIntegMoteur_MethodeEqTarif.simulations
            Get
                Return _simulations
            End Get
        End Property
#End Region

#Region "Calculs"

#Region "Initialisation des calculs"

#Region "Table en entrée + Tables de travail"
        ''' <summary>
        ''' Initialisation des tables de travail nécessaires au modèle 1
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub init_tbles_travail(ByVal Referentiel As IReferentielOMANE) Implements IIntegMoteur_MethodeEqTarif.init_tbles_travail

            TableMortalite_H_Initialize(Referentiel)
            TableMortalite_F_Initialize(Referentiel)
            TableMaintienINCINV_Fra_Initialize(Referentiel)
            TableMaintienINCINV_Tx_Initialize(Referentiel)

            'Ligne ajoutée pour la version SAS (calcul sous SAS de la table d'entrée de traitMoteur1) :
            TraitementEntree.Calculer_BDD()
            TraitementEntree.Calculer_DataTable()

            'Récupération de la table de travail dans une variable
            _tble_travail = TraitementEntree.DataTableResultat
            If DataSetOMANE.Tables.Contains(_tble_travail.TableName) Then DataSetOMANE.Tables.Remove(_tble_travail.TableName)
            DataSetOMANE.Tables.Add(_tble_travail)
        End Sub

        Private Sub TableMortalite_H_Initialize(ByVal Referentiel As IReferentielOMANE)
            Dim NomTableMortaliteH As String = _
                (From InfoTable As IInfoTableReferentiel In Referentiel.TablesMortalite.InfoTables
                Select InfoTable
                Where InfoTable.NomFichier = listeParametres.Table_Mortalite_H.ValeurUnique.ToString).AsEnumerable.FirstOrDefault.NomTable

            m_tble_mortalite_H = Referentiel.TablesMortalite.Factory.Item(NomTableMortaliteH)
        End Sub
        Private Sub TableMortalite_F_Initialize(ByVal Referentiel As IReferentielOMANE)
            Dim NomTableMortaliteF As String = _
                (From InfoTable As IInfoTableReferentiel In Referentiel.TablesMortalite.InfoTables
                Select InfoTable
                Where InfoTable.NomFichier = listeParametres.Table_Mortalite_F.ValeurUnique.ToString).AsEnumerable.FirstOrDefault.NomTable

            m_tble_mortalite_F = Referentiel.TablesMortalite.Factory.Item(NomTableMortaliteF)
        End Sub
        Private Sub TableMaintienINCINV_Fra_Initialize(ByVal Referentiel As IReferentielOMANE)
            Dim NomTableMaintienINCINV_Fra = _
                (From InfoTable As IInfoTableReferentiel In Referentiel.TablesINCINV_Fra.InfoTables
                Select InfoTable
                Where InfoTable.NomFichier = listeParametres.tble_maintien_incinvFRA.ValeurUnique.ToString).AsEnumerable.FirstOrDefault.NomTable

            m_TbleINCINVFra = Referentiel.TablesINCINV_Fra.Factory.Item(NomTableMaintienINCINV_Fra)
        End Sub
        Private Sub TableMaintienINCINV_Tx_Initialize(ByVal Referentiel As IReferentielOMANE)
            Dim NomTableMaintienINCINV_Tx = _
                (From InfoTable As IInfoTableReferentiel In Referentiel.TablesINCINV_Tx.InfoTables
                 Select InfoTable
                 Where InfoTable.NomFichier = listeParametres.Tble_maintien_incinv.ValeurUnique).AsEnumerable.FirstOrDefault.NomTable

            m_TbleINCINVTaux = Referentiel.TablesINCINV_Tx.Factory.Item(NomTableMaintienINCINV_Tx)
        End Sub
#End Region

        ''' <summary>
        ''' Permet d'initialiser la procédure de calcul
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub calculeInit() Implements IIntegMoteur_MethodeEqTarif.calculeInit
            If Optimise Then
                TempsChgtTable = 0
                TimeChgtTable1 = 0
                TimeChgtTable2 = 0
                TempsFonctCalculPrinc = 0
                TimeFonctCalculPrinc1 = 0
                TimeFonctCalculPrinc2 = 0
                TempsFonctCalculSecondaire = 0
                TimeFonctCalculSecondaire1 = 0
                TimeFonctCalculSecondaire2 = 0
                TimeChgtTable1 = Timer
            End If

            init_tbles_travail(Referentiel)
        End Sub
#End Region

#Region "Héritage classe traitement (vide à l'heure actuelle)"
        ''' <summary>
        ''' 
        ''' </summary>
        ''' <remarks></remarks>
        Protected Overrides Sub execute_DataTable()
            MsgBox("Fonction à modifier")
        End Sub

        'Public Overrides Function execute_DataTableToDgv(ByVal stockageBDDlocale As Boolean, ByVal dgv As System.Windows.Forms.DataGridView) As System.Data.DataTable
        '    MsgBox("La fonction execute_DataTableToDgv du moteur de calcul 1 est en cours de développement")
        '    Return Nothing
        'End Function

        ''' <summary>
        ''' 
        ''' </summary>
        ''' <remarks></remarks>
        Protected Overrides Sub execute_BDD()
            'Vérifier que le traitement est à jour dans la base de données
        End Sub
#End Region

        ''' <summary>
        ''' Permettant de calculer le scénario central
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub calculerScenarioCentral() Implements IIntegMoteur_MethodeEqTarif.calculerScenarioCentral
            _scenarioCentral.Calculer()
        End Sub

        ''' <summary>
        ''' Permettant de calculer toutes les simulations
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub calculerSimulations() Implements IIntegMoteur_MethodeEqTarif.calculerSimulations
            simulations.Calculer()
        End Sub

        ''' <summary>
        ''' Procédure de calcul, utilisée à la fois par le scénario central et les simulations
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub calcule(ByVal isScenarioCentral As Boolean, Optional SimulChoc As SimulationChoc = Nothing) Implements IIntegMoteur_MethodeEqTarif.calcule

            'Le tableau PrimesParCSR contient, pour chaque segment, les informations suivantes :
            '   - 1ere colonne : les CSR (indice 0)
            '   - 2eme colonne : la prime pure (indice 1)
            '   - 3eme colonne : la prime technique (indice 2)
            Dim PrimesParCSR(_tble_travail.Rows.Count - 1, 2)
            Dim parametres_decl As Hashtable = _coll_param.GetParamDecl
            Dim parametres_uniq As Hashtable = _coll_param.getParamUniq
            Dim ageSous_Actu As Double, _
                nbPer As Double, _
                txNomPer As Double, _
                txMort_Actu As Double, _
                ageFinDC As Double, _
                ageFinINCINV As Double
            Dim TableMort As ITableMortalite
            Dim sommeCSR As Double = 0, CI As Double = 1, PPures() As Double, numSegment As Integer = 0
            Dim PPSegment As Double, PPureDC As Double, PPureINCINV As Double

            If isScenarioCentral Then calculeTableTravailAjouteColonnes()

            If Optimise Then
                TimeChgtTable2 = Timer
                TempsChgtTable = TimeChgtTable2 - TimeChgtTable1
                MsgBox("Le nombre total d'itérations à réaliser est de " & _tble_travail.Rows.Count & vbCrLf & _
                       "Le temps de chargement des tables de travail a été de " & TempsChgtTable)
                TimeFonctCalculPrinc1 = Timer
            End If

            Dim compteur As Integer = 0
            Dim TempsDeb As Double = Timer
            Dim TempsFin As Double

            For Each r As DataRow In _tble_travail.Rows

                If Optimise Then
                    compteur += 1
                    If compteur = 100 Then
                        TempsFin = Timer
                        Dim TempsEcouleSec As Double = TempsFin - TempsDeb
                        Dim TempsEstimeMin As Double = ((TempsEcouleSec / compteur) * _tble_travail.Rows.Count) / 60
                        TimeFonctCalculPrinc2 = Timer
                        TempsFonctCalculPrinc = TempsFonctCalculPrinc + (TimeFonctCalculPrinc2 - TimeFonctCalculPrinc1)
                        MsgBox("Vous avez atteint la 100ème itération en " & TempsFin - TempsDeb & " secondes." & vbCrLf & _
                               "Le temps estimé (en minutes) pour effectuer le calcul est de " & TempsEstimeMin & vbCrLf & _
                               "Le % de temps passé dans la fonction principale est de : " & TempsFonctCalculPrinc / (TempsFonctCalculPrinc + TempsFonctCalculSecondaire) & vbCrLf & _
                               "Le % temps passé dans la fonction secondaire est de : " & TempsFonctCalculSecondaire / (TempsFonctCalculPrinc + TempsFonctCalculSecondaire))
                    End If
                End If

                'En fonction du paramètre à choquer, MAJ de la DataTable en entrée pour intégrer le choc
                If SimulChoc IsNot Nothing Then
                    r(SimulChoc.NomParametre) = r(SimulChoc.NomParametre) + SimulChoc.ValeurChoc
                End If

                ' ''Mise à jour des valeurs en cours des paramètres déclinés (y compris sensibilités)
                ''For Each p As IParametre In parametres_decl.Values
                ''    p.ValeurEnCoursAsObject = r.GetChildRows("relParam" & p.Nom)(0)(p.Nom)
                ''Next

                'Mise à jour des paramètres nécessaires au calcul de l'échéancier
                sommeCSR = sommeCSR + r(nomSumCSR)
                txMort_Actu = r(nomTxMort_Actu) '_coll_param.TxMort_Actu.ValeursEnCours
                If r(nomSexeAssu) = "H" Then TableMort = m_tble_mortalite_H Else TableMort = m_tble_mortalite_F

                ageSous_Actu = rechercheVdoubleMin(TableMort.DataTable, _
                    r(nomTxMort_Actu), _
                    nomTxMortAn, _
                    nomAgeAnEntier)

                nbPer = CType(r(nomDuree_Actu), Integer) '_coll_param.Duree_Actu.ValeursEnCours
                txNomPer = (1 + r(nomTxNom_Actu)) ^ (1 / 12) - 1
                ageFinDC = r(nomAge_FinDC) '_coll_param.Age_FinDC.ValeursEnCours
                ageFinINCINV = r(nomAge_FinINCINV)  '_coll_param.Age_FinINCINV.ValeursEnCours


                'Calcul des primes pures DC et INC/INV
                PPures = PP_DC_INCINV_OutilsNA(nbPer,
                                               r(nomTx_TechA),
                                               txNomPer,
                                               CI,
                                               ageSous_Actu,
                                               r(nomSexeAssu),
                                               ageFinDC,
                                               ageFinINCINV,
                                               r(nomTx_mensEntreeINCINV),
                                               TableMort, m_TbleINCINVFra, m_TbleINCINVTaux)


                PPureDC = PPures(0)
                If r(nomIdOption) = "DC/PTIA" Then
                    PPureINCINV = 0
                Else
                    PPureINCINV = PPures(1)
                End If

                'Calcul de la prime pure du segment
                PPSegment = PPureDC * 12 _
                * (1 + r(nomTx_PrixGarantiePTIA)) _
                + PPureINCINV * 12 _
                * (1 + r(nomTx_chgtSecuINCINV)) _
                * (1 - r(nomTx_abat_MalaNonObje)) _
                * (1 - r(nomTx_abat_ExclPerteRev))


                'Calcul des primes technique DC et INC/INV
                Dim Adc, Bdc, PtechDC, Aincinv, Bincinv, PtechINCINV As Double
                Adc = -(r(nomPourDC_Derog_Actu) * r(nomPComDC_Derog_Actu) _
                        + (1 - r(nomPourDC_Derog_Actu)) * r(nomPComDC_Non_Derog_Actu))
                Bdc = -(1 - r(nomTx_fraiGestA)) * Adc
                PtechDC = r(nomTx_CommiContA) * Adc _
                          - (1 - r(nomTx_fraiGestA)) * Adc

                Aincinv = -(r(nomPourINCINV_Derog_Actu) * r(nomPComINCINV_Derog_Actu) _
                            + (1 - r(nomPourINCINV_Derog_Actu)) * r(nomPComINCINV_Non_Derog_Actu)) _
                            / (1 + r(nomTx_TaxeAssu))

                Bincinv = -(1 - r(nomTx_fraiGestA)) * Aincinv
                PtechINCINV = r(nomTx_CommiContA) _
                              * Aincinv - (1 - r(nomTx_fraiGestA)) * Aincinv

                PrimesParCSR(numSegment, 0) = r(nomSumCSR)
                PrimesParCSR(numSegment, 1) = PPSegment
                If r("id_option") = "DC/PTIA" Then
                    PrimesParCSR(numSegment, 2) = PtechDC
                Else
                    PrimesParCSR(numSegment, 2) = PtechDC + PtechINCINV
                End If

                If isScenarioCentral Then
                    r("AGESOUS_ACTU") = ageSous_Actu
                    r(nomDuree_Actu) = nbPer
                    r("PP_DC") = PPureDC
                    r("PP_INCINV") = PPureINCINV
                    r("PP_SEGMENT") = PPSegment
                    r("PTECH_SEGMENT") = PrimesParCSR(numSegment, 2)
                    r(nomNbPer_Actu) = nbPer
                End If

                'En fonction du paramètre à choquer, MAJ de la DataTable en entrée pour retirer l'effet du choc
                If SimulChoc IsNot Nothing Then
                    r(SimulChoc.NomParametre) = r(SimulChoc.NomParametre) - SimulChoc.ValeurChoc
                End If

                numSegment = numSegment + 1

            Next

            Dim pTechPf As Double = 0
            Dim pPurePf As Double = 0
            Dim poidsCSR As Double = 0
            For i As Integer = 0 To numSegment - 1
                poidsCSR = PrimesParCSR(i, 0) / sommeCSR
                pPurePf = pPurePf + PrimesParCSR(i, 1) * poidsCSR
                pTechPf = pTechPf + PrimesParCSR(i, 2) * poidsCSR
            Next

            If isScenarioCentral Then
                For Each r As DataRow In _tble_travail.Rows
                    'On ajoute une colonne poids à chaque segment du portefeuille
                    r("POIDS_CSR") = r(nomSumCSR) / sommeCSR
                    'pTechPf = pTechPf + r("PTECH_SEGMENT") * r("POIDS_CSR")
                    'pPurePf = pPurePf + r("PP_SEGMENT") * r("POIDS_CSR")
                Next
            End If

            _resultatsCalcul.PPurePf = pPurePf
            _resultatsCalcul.PTechPf = pTechPf
            _resultatsCalcul.sommeCSR = sommeCSR

        End Sub

        ''' <summary>
        ''' Permet de rétablir l'environnement de travail à la fin de la procédure de calcul
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub calculeCloture() Implements IIntegMoteur_MethodeEqTarif.calculeCloture
        End Sub

#Region "Fonctions privées spécifiques à la méthode de l'équilibre tarifaire et intervenant dans les calculs"
        ''' <summary>
        ''' 
        ''' </summary>
        ''' <remarks></remarks>
        Private Function PP_DC_INCINV_OutilsNA(ByVal nbPer As Integer,
                                               ByVal txTechA As Double,
                                               ByVal txNomPer As Double,
                                               ByVal CI As Double,
                                               ByVal ageSous As Integer,
                                               ByVal sexeAssu As String,
                                               ByVal ageFinDC As Double,
                                               ByVal ageFinINCINV As Double,
                                               ByVal TxEntreeINCINV_Mens As Double,
                                               ByVal TableMort As ITableMortalite,
                                               ByVal TableMaintINCINV_Fra As ITableMaintienINCINV_Fra,
                                               ByVal TableMaintINCINV_Tx As ITableMaintienINCINV_Tx) As Double()

            'Calcul de la prime pure DC - Pour que l'outil soit plus rapide, on raisonne sur des tableaux
            'et non pas sur des objets
            'Le tableau contient une ligne par période -> dans la 1ere version, le raisonnement
            'est fait sur du mensuel
            'L'échéancier se présente de la façon suivante :
            '   - Colonne 0 : le CRD de la (i+1)ème période (le tableau commence à l'indice 0)
            '   - Colonne 1 : l'age de l'assuré en début de période
            '   - Colonne 2 : le taux de mortalité mensuel de la période (s'il s'agit d'un homme ou d'une femme)
            '   - Colonne 3 : la probabilité de survie dans le crédit jusqu'au début de la période
            '   - Colonne 4 : la valeur probable de la prestation
            '   - Colonne 5 : la valeur actuelle probable de la prestation DC
            '   - Colonne 6 : la valeur actuelle probable de l'assiette de prime
            '   - Colonne 7 : la valeur actuelle probable de la prestation probable en INC/INV

            Dim echeancier(nbPer - 1, 7) As Double
            Dim VAP_deces As Double = 0, VAP_INCINV As Double = 0, VAP_assiette As Double = 0
            Dim mensualite As Double = (-1) * Microsoft.VisualBasic.Pmt(txNomPer, nbPer, CI, , DueDate.EndOfPeriod)

            'Initialisation de l'échéancier
            echeancier(0, 0) = CI
            echeancier(0, 1) = ageSous
            'Remarque1 : Attention au calcul des taux mensuels dans l'outil NA
            'Remarque2 : Attention au calcul des âges dans l'outil NA
            echeancier(0, 2) = TableMort.TxMortalite(ageSous) / 12
            ' echeancier(0, 2) = IIf(sexeAssu = "H", m_tble_mortalite_H, m_tble_mortalite_F).Rows(ageSous)(nomTxMortAn) / 12
            echeancier(0, 3) = 1
            echeancier(0, 4) = (echeancier(0, 0) * echeancier(0, 2) * echeancier(0, 3))
            echeancier(0, 5) = CI * echeancier(0, 2) * echeancier(0, 3) _
                               * (1 + txTechA) ^ (-(0.5) / 12)
            echeancier(0, 6) = CI * (1 + txTechA) ^ (-(0.5) / 12)
            echeancier(0, 7) = 0

            VAP_deces = echeancier(0, 5)
            VAP_assiette = echeancier(0, 6)

            'Récurrence sur l'échéancier
            For i = 1 To nbPer - 1



                Dim age As Double = ageSous + i / 12

                If txNomPer = 0 Then txNomPer = 0.000000001
                'If txNomPer = Double.Epsilon Then
                'End If

                echeancier(i, 0) = CI * ((1 + txNomPer) ^ nbPer - (1 + txNomPer) ^ i) / ((1 + txNomPer) ^ nbPer - 1)
                echeancier(i, 1) = ageSous + CType(i / 12, Integer)

                ' ********************************************************


                'echeancier(i, 2) = (IIf(sexeAssu = "H", _tble_mortalite_H, _table_mortalite_F).Rows(ageSous + CType((i / 12) + 0.000000001, Integer))((nomTxMortAn))) / 12
                Dim AgeRech As Integer = ageSous + CType((i / 12) + 0.000000001, Integer)

                'TimeFonctCalculSecondaire1 = Timer
                'TimeFonctCalculPrinc2 = Timer
                'TempsFonctCalculPrinc = TempsFonctCalculPrinc + (TimeFonctCalculPrinc2 - TimeFonctCalculPrinc1)

                'TimeFonctCalculPrinc1 = Timer
                'TimeFonctCalculSecondaire2 = Timer
                'TempsFonctCalculSecondaire = TempsFonctCalculSecondaire + (TimeFonctCalculSecondaire2 - TimeFonctCalculSecondaire1)

                echeancier(i, 2) = TableMort.TxMortalite(AgeRech) / 12 'm_tble_mortalite_H.Rows(AgeRech)(nomTxMortAn)

                ' ********************************************************


                echeancier(i, 3) = echeancier(i - 1, 3) * (1 - echeancier(i, 2))
                'Attention, l'actualisation de la valeur probable des prestations DC
                's'effectue en taux proportionnel (tx_annuel/12). Ce n'est pas cohérent avec le calcul des CRD
                'Hypothèse de paiement des sinistres en milieu de période

                echeancier(i, 4) = (echeancier(i, 0) * echeancier(i, 2) * echeancier(i, 3))
                If age < ageFinDC Then
                    echeancier(i, 5) = (echeancier(i, 0) * echeancier(i, 2) * echeancier(i, 3)) * (1 + txTechA) ^ (-(i + 0.5) / 12)
                Else
                    echeancier(i, 5) = 0
                End If
                echeancier(i, 6) = CI * echeancier(i, 3) * (1 + txTechA) ^ (-(i + 0.5) / 12)

                'Prestation probable en INCINV (dans la version 1, on fixe la franchise à 3 mois)
                If i <= 3 Or age >= ageFinINCINV Then
                    echeancier(i, 7) = 0
                Else
                    'On calcule, de même que dans le fichier de recette, durée-numPériode
                    Dim dureeCouvINC As Integer = Math.Min(36, nbPer - i)
                    Dim tx_HorsFra As Double = TableMaintINCINV_Tx.ProbaMaintien(dureeCouvINC, ageSous)
                    'On récupère le taux d'entrée (ici 0,5 pour simplifier)
                    Dim tx_entree As Double = TxEntreeINCINV_Mens

                    'On applique un taux constant car la franchise est fixée à 3 mois
                    Dim tx_reducFRA As Double = TableMaintINCINV_Fra.TauxAbattement_Fra(3, ageSous)

                    'On mpultiplie par la proba de survie dans le crédit
                    echeancier(i, 7) = (tx_entree * mensualite * tx_HorsFra * tx_reducFRA * echeancier(i, 3)) * (1 + txTechA) ^ (-(i + 0.5) / 12)

                End If
                VAP_deces = VAP_deces + echeancier(i, 5)
                VAP_assiette = VAP_assiette + echeancier(i, 6)
                VAP_INCINV = VAP_INCINV + echeancier(i, 7)
            Next

            Dim result(1) As Double
            result(0) = VAP_deces / VAP_assiette
            result(1) = VAP_INCINV / VAP_assiette

            Return result

        End Function

        ''' <summary>
        ''' 
        ''' </summary>
        ''' <remarks></remarks>
        Private Sub calculeTableTravailAjouteColonnes()
            'Ajout à la table de travail des colonnes nécessaires au moteur de calcul
            With _tble_travail.Columns
                If Not .Contains("PP_DC") Then .Add("PP_DC", GetType(Double))
                If Not .Contains("PP_INCINV") Then .Add("PP_INCINV", GetType(Double))
                If Not .Contains("AGESOUS_ACTU") Then .Add("AGESOUS_ACTU", GetType(Double))
                If Not .Contains("PP_SEGMENT") Then .Add("PP_SEGMENT", GetType(Double))
                If Not .Contains("PTECH_SEGMENT") Then .Add("PTECH_SEGMENT", GetType(Double))
                If Not .Contains("POIDS_CSR") Then .Add("POIDS_CSR", GetType(Double))
            End With
        End Sub
#End Region

#End Region

#Region "Traitement des évènements reçus de l'extérieur"

#Region "Gestion des Handles"
        ''' <summary>
        ''' Abonnement de la classe aux évènements qui lui sont utiles
        ''' </summary>
        ''' <remarks></remarks>
        Private Sub addHandlers()
            'Placer le moteur 1 comme observateur de tous les paramètres influençant son calcul
            'Cette classe joue ici le rôle de médiateur et de façade
            AddHandler _scenarioCentral.EtatCalculChanged, AddressOf onScenarioCentralEtatCalculChanged
            AddHandler _simulations.EtatCalculChanged, AddressOf onSimulationsEtatCalculChanged
            addHandlersListeParametres()
        End Sub

        ''' <summary>
        ''' Abonnement de la classe aux évènements générés par les paramètres
        ''' </summary>
        ''' <remarks></remarks>
        Private Sub addHandlersListeParametres()
            If Not _coll_param Is Nothing Then
                For Each param As BaseParametre In _coll_param.Values
                    If param.Methode_Cal(0) Then
                        AddHandler param.hasChanged, AddressOf onParametreChanged
                    End If
                Next
            End If
        End Sub

        ''' <summary>
        ''' Désabonnement de la classe aux évènements générés par les paramètres
        ''' </summary>
        ''' <remarks></remarks>
        Private Sub RemoveHandlersListeParametres()
            If Not _coll_param Is Nothing Then
                For Each param As BaseParametre In _coll_param.Values
                    If param.Methode_Cal(0) Then RemoveHandler param.hasChanged, AddressOf onParametreChanged
                Next
            End If
        End Sub
#End Region

        Private Sub onScenarioCentralEtatCalculChanged(ByVal sender As Object, ByVal e As EventArgs)
            If _scenarioCentral.EtatCalcul <> ValueEtatCalcul.A_JOUR Then
                _simulations.Invalider()
            End If
            RaiseEvent EtatCalculScenCentralChanged(Me, e)
        End Sub
        Private Sub onSimulationsEtatCalculChanged(ByVal sender As Object, ByVal e As EventArgs)
            RaiseEvent EtatCalculSimulationsChanged(Me, e)
        End Sub
        Private Sub onParametreChanged(ByVal sender As Object, ByVal e As EventArgs)
            _scenarioCentral.Invalider()
        End Sub

        ''' <summary>
        ''' Le traitement en entrée du moteur de calcul a été modifié. La notification est envoyée par la liste de
        ''' traitements OMANE
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub onTraitEntree_EtatCalculDataTableChanged(ByVal sender As Object, ByVal e As EventArgs) Implements IIntegMoteur_MethodeEqTarif.onTraitEntree_EtatCalculDataTableChanged
            If CType(sender, Traitement).EtatCalcul_DataTable = ValueEtatCalcul.A_MAJ Then
                Me._scenarioCentral.Invalider()
            End If
        End Sub

#End Region

#Region "Evènements générés"
        Public Event EtatCalculScenCentralChanged As EventHandler Implements IIntegMoteur_MethodeEqTarif.EtatCalculScenCentralChanged
        Public Event EtatCalculSimulationsChanged As EventHandler Implements IIntegMoteur_MethodeEqTarif.EtatCalculSimulationsChanged
#End Region

    End Class

End Namespace
